import requests
import json
import logging
import os
import configparser
from datetime import datetime
from typing import Dict, Any, Optional
from config import ENV, BASE_DIR, CONFIG_PATH


class WeChatPush:
    """企业微信推送类"""
    
    def __init__(self, webhook_url: str = None):
        """
        初始化企业微信推送
        :param webhook_url: webhook地址，如果不传则使用默认地址
        """
        # 从配置文件读取默认 webhook，如果调用方传入则优先生效
        self.webhook_url = webhook_url or self._read_webhook_from_config()
        self.template_path = os.path.join(BASE_DIR, 'common', 'message_template.json')

    def _read_webhook_from_config(self) -> Optional[str]:
        try:
            config = configparser.ConfigParser()
            config.read(CONFIG_PATH, encoding='utf-8')
            if config.has_section('wechat'):
                url = config.get('wechat', 'webhook_url', fallback=None)
                if url:
                    return url.strip()
        except Exception as e:
            logging.warning(f"读取企业微信webhook配置失败: {e}")
        # 兜底返回None，由上层调用处理
        return None
    
    def load_template(self, template_type: str) -> Dict[str, Any]:
        """
        加载消息模板
        :param template_type: 模板类型 (record/execute)
        :return: 模板配置
        """
        try:
            with open(self.template_path, 'r', encoding='utf-8') as f:
                templates = json.load(f)
            
            if template_type not in templates:
                raise ValueError(f"未找到模板类型: {template_type}")
            
            return templates[template_type]
        except FileNotFoundError:
            logging.error(f"模板文件未找到: {self.template_path}")
            raise
        except json.JSONDecodeError:
            logging.error(f"模板文件格式错误: {self.template_path}")
            raise
    
    def format_message(self, template_type: str, result: str = "成功", 
                      custom_data: Dict[str, Any] = None) -> Dict[str, Any]:
        """
        格式化消息内容
        :param template_type: 模板类型 (record/execute)
        :param result: 执行结果
        :param custom_data: 自定义数据，用于覆盖模板中的变量
        :return: 格式化后的消息
        """
        template = self.load_template(template_type)
        
        # 默认变量
        current_time = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
        variables = {
            "environment": ENV,
            "test_time": current_time,
            "result": result,
            "current_date": datetime.now().strftime("%Y-%m-%d"),
            "current_time": datetime.now().strftime("%H:%M:%S")
        }
        
        # 合并自定义数据
        if custom_data:
            variables.update(custom_data)
        
        # 替换模板中的变量
        content = template["content"]
        for key, value in variables.items():
            placeholder = "{" + key + "}"
            content = content.replace(placeholder, str(value))
        
        # 构建markdown消息
        message = {
            "msgtype": "markdown",
            "markdown": {
                "content": content
            }
        }
        
        return message
    
    def send_message(self, template_type: str, result: str = "成功", 
                    custom_data: Dict[str, Any] = None) -> bool:
        """
        发送消息
        :param template_type: 模板类型 (record/execute)
        :param result: 执行结果
        :param custom_data: 自定义数据
        :return: 发送是否成功
        """
        try:
            message = self.format_message(template_type, result, custom_data)
            
            logging.info(f"准备发送企业微信消息: {json.dumps(message, ensure_ascii=False, indent=2)}")
            
            response = requests.post(
                self._ensure_webhook_url(),
                json=message,
                headers={'Content-Type': 'application/json'},
                timeout=10
            )
            
            response.raise_for_status()
            result_data = response.json()
            
            if result_data.get('errcode') == 0:
                logging.info("企业微信消息发送成功")
                return True
            else:
                logging.error(f"企业微信消息发送失败: {result_data}")
                return False
                
        except requests.exceptions.RequestException as e:
            logging.error(f"发送企业微信消息网络异常: {e}")
            return False
        except Exception as e:
            logging.error(f"发送企业微信消息异常: {e}")
            return False

    def _ensure_webhook_url(self) -> str:
        if not self.webhook_url:
            raise RuntimeError("未配置企业微信 webhook_url，请在 common/config.{ENV}.ini 的 [wechat] 中配置，或初始化时传入")
        return self.webhook_url
    
    def send_record_notification(self, result: str = "成功", custom_data: Dict[str, Any] = None) -> bool:
        """
        发送录制自动化脚本通知
        :param result: 执行结果
        :param custom_data: 自定义数据
        :return: 发送是否成功
        """
        return self.send_message("record", result, custom_data)
    
    def send_execute_notification(self, result: str = "成功", custom_data: Dict[str, Any] = None) -> bool:
        """
        发送执行自动化脚本通知
        :param result: 执行结果
        :param custom_data: 自定义数据
        :return: 发送是否成功
        """
        return self.send_message("execute", result, custom_data)


def log_info(msg):
    """日志信息输出"""
    logging.info(msg)


def log_error(msg):
    """日志错误输出"""
    logging.error(msg)


# 便捷函数
def send_wechat_notification(template_type: str, result: str = "成功", 
                           custom_data: Dict[str, Any] = None, 
                           webhook_url: str = None) -> bool:
    """
    发送企业微信通知的便捷函数
    :param template_type: 模板类型 (record/execute)
    :param result: 执行结果
    :param custom_data: 自定义数据
    :param webhook_url: webhook地址
    :return: 发送是否成功
    """
    push = WeChatPush(webhook_url)
    return push.send_message(template_type, result, custom_data)


if __name__ == "__main__":
    # 测试示例
    from config import setup_logger
    setup_logger()
    
    # 测试录制通知
    push = WeChatPush()
    
    # 发送录制通知
    log_info("测试发送录制通知...")
    push.send_record_notification("成功", {"script_name": "自动化录制脚本"})
    
    # 发送执行通知
    log_info("测试发送执行通知...")
    push.send_execute_notification("成功", {"script_name": "执行自动化脚本", "test_cases": 5})
